(function ($) {

    var TreeAutocompletePager = function (element, option) {
        this.element = element;
        $(element).addClass('tree-autocomplete iconic-input right');

        // this.icon = $('<i class="fa fa-sort"></i>');
        // $(element).append(this.icon);

        // this.input = $(element).find('input[type=text]');
        this.input = $('<input type="text" class="select-group" placeholder="' + option.defaultText + '">').css('width', '100%');
        $(element).append(this.input);

        // this.valueInput = $(element).find('input[type=hidden]');
        this.valueInput = $('<input type="hidden" name="' + $(element).attr('id') + '_code_name' + '" id="' + $(element).attr('id') + '_code_value">');
        $(element).append(this.valueInput);

        this.idInput = $('<input type="hidden" name="' + $(element).attr('id') + '_id_name' + '" id="' + $(element).attr('id') + '_id_value">');
        $(element).append(this.idInput);

        // this.menu = $(element).find('.dropdown-menu');
        this.menu = $('<ul class="dropdown-menu"></ul>');
        $(element).append(this.menu);

        this.isShown = false;
        this.isDisabled = false;

        // this.source = option.source;

        this.source = [];
        this.page = 0;
        this.pageSize = 15;
        this.isGetData = true;
        this.itemId = null;
        this.isAsync = true;
        this.url = option.url;
        this.clear = false;
        this.level = null;
        this.interval = null;

        this.query = '';

        this.onSelected = option.onSelected;

        this.isShowCode = true;
        if (option.isShowCode != undefined) {
            this.isShowCode = option.isShowCode;
        }

        // this.init();
    };

    TreeAutocompletePager.prototype = {
        init: function () {
            this.process();

            this.listen();
        }

        , listen: function () {
            this.input
            // .on('dblclick', $.proxy(this.dblclick, this))
                .on('click', $.proxy(this.inputClick, this))
                .on('focus', $.proxy(this.focus, this))
                .on('blur', $.proxy(this.blur, this))
                .on('keypress', $.proxy(this.keypress, this))
                .on('keyup', $.proxy(this.keyup, this))
                .on('keydown', $.proxy(this.keydown, this))
                .on('input', $.proxy(this.inputChange, this));

            // if (this.eventSupported('keydown')) {
            //     this.input.on('keydown', $.proxy(this.keydown, this));
            // }

            this.menu
                .on('click', $.proxy(this.click, this))
                .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
                .on('mouseleave', 'li', $.proxy(this.mouseleave, this));

            var that = this;
            this.menu.scroll(function () {
                var ulHeight = $(this).height();
                var nScrollHeight = $(this)[0].scrollHeight;
                var nScrollTop = $(this)[0].scrollTop;
                if (nScrollTop + ulHeight >= nScrollHeight - 10) {
                    that.process();
                    $(this).scrollTop($(this)[0].scrollHeight);
                }
            });

            // this.icon.on('click', $.proxy(this.iconClick, this));
        }

        , show: function () {
            if (this.isDisabled == true) {
                return this;
            }

            this.menu.show();
            this.isShown = true;
            return this;
        }

        , hide: function () {
            this.menu.hide();
            this.isShown = false;
            return this;
        }

        , inputChange: function () {
            // this.query = this.input.val();
            // this.query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&');
            //
            // this.source.length = 0;
            // this.page = 0;
            // this.isGetData = true;
            // this.itemId = null;
            // this.isAsync = true;
            // this.clear = true;
            // this.level = null;
            //
            // this.process();
            // if (this.menu.find('li').length > 0) {
            //     this.input.removeClass('disabled');
            //     this.show();
            // } else {
            //     this.valueInput.val(null);
            //     this.idInput.val(null);
            //     this.element.val(null);
            //     this.input.addClass('disabled');
            //     this.hide();
            // }
            //
            // if (!this.input.val()) {
            //     this.valueInput.val(null);
            //     this.idInput.val(null);
            //     this.element.val(null);
            // }

            if (this.interval) {
                clearInterval(this.interval);
            }

            this.interval = setInterval(this._inputChange(this), 2000);
        }

        , _inputChange: function (ele) {
            return function () {
                ele.inputChange2(ele);
            }
        }

        , inputChange2: function (ele) {
            clearInterval(ele.interval);

            ele.query = ele.input.val();
            ele.query = ele.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&');

            ele.source.length = 0;
            ele.page = 0;
            ele.isGetData = true;
            ele.itemId = null;
            ele.isAsync = true;
            ele.clear = true;
            ele.level = null;

            ele.process();
            if (ele.menu.find('li').length > 0) {
                ele.input.removeClass('disabled');
                ele.show();
            } else {
                ele.valueInput.val(null);
                ele.idInput.val(null);
                ele.element.val(null);
                ele.input.addClass('disabled');
                ele.hide();
            }

            if (!ele.input.val()) {
                ele.valueInput.val(null);
                ele.idInput.val(null);
                ele.element.val(null);
            }
        }

        , process: function () {
            if (this.isGetData) {
                var data = {};
                data.page = this.page;
                data.pageSize = this.pageSize;
                data.name = this.query;
                data.id = this.itemId;
                var that = this;
                requestJson(this.url, data, this.isAsync, function (response) {
                    if (response.status == 0) {
                        if (response.data && response.data.length > 0) {
                            // that.source = that.source.concat(response.data);

                            that.source = response.data;
                            that.matcher(that.source);
                            var filterData = that.filter(that.source);
                            that.render(filterData);

                            that.page += 1;
                        } else {
                            if (that.clear) {
                                that.menu.html('');
                            }
                            that.isGetData = false;
                        }
                    }

                });
            }
        }

        , isMatcher: function (item) {
            return (item.toLowerCase().indexOf(this.query.toLowerCase())) == -1 ? 0 : 1;
        }

        , matcher: function (items) {
            var that = this;
            var isMatcher = false;
            $(items).each(function () {
                if (that.isMatcher(this.name + this.code)) {
                    this.is_matcher = true;
                    isMatcher = true;
                } else {
                    this.is_matcher = false;
                }

                var isChildrenMatcher = false;
                if (this.children) {
                    isChildrenMatcher = that.matcher(this.children);
                }

                this.is_children_matcher = isChildrenMatcher;
                if (isChildrenMatcher) {
                    isMatcher = true;
                }
            });

            return isMatcher;
        }

        , filter: function (items) {
            var that = this;
            var data = [];
            $(items).each(function () {
                if (this.is_matcher || this.is_children_matcher) {
                    if (this.children) {
                        this.filterChildren = that.filter(this.children);
                    }
                    data.push(this);
                }
            });

            for (var i = 0; i < data.length; i++) {
                if (i == data.length - 1) {
                    data[i].is_last = true;
                } else {
                    data[i].is_last = false;
                }
            }

            if (data.length == 0) {
                data = null;
            }

            return data;
        }

        , render: function (filterData) {
            if (this.clear) {
                this.menu.html('');
                this.clear = false;
            }

            this.menu.append(this.renderLevel(filterData, 0));

            var code = this.valueInput.val();
            var hasItemSelected = false;
            if (code != null) {
                this.menu.find('li').each(function () {
                    if ($(this).find('a').attr('data-value') == code) {
                        $(this).addClass('active');
                        hasItemSelected = true;
                        return false;
                    }
                });
            }

            if (!hasItemSelected) {
                $(this.menu.find('li').not('.disabled')[0]).addClass('active');
            }

            this.offset();
        }

        , renderLevel: function (items, level) {
            var itemsElement = $('<div></div>');
            var that = this;
            $(items).each(function () {
                if (this.is_matcher || this.is_children_matcher) {
                    var displayName = "";
                    if (that.isShowCode) {
                        displayName = that.highlighter(this.name + " 【 " + this.code + " 】");
                    } else {
                        displayName = that.highlighter(this.name);
                    }
                    var prefix = '';

                    if (that.level == null) {
                        that.level = this.code_tree.split('-').length; //设置起始层
                    }


                    for (var i = 0; i < this.code_tree.split('-').length - that.level; i++) {
                        prefix += ' &nbsp;&nbsp;&nbsp;&nbsp;';
                    }

                    if (this.code_tree.split('-').length - that.level == 0) {
                        displayName = displayName;
                    }
                    else {
                        displayName = '┗&nbsp;&nbsp;' + displayName;
                    }
                    displayName = prefix + displayName;
                    var item = $('<li><a href="#" data-name="' + this.name + '" data-value="' + this.code + '"data-id="' + this.id + '">' + displayName + '</a></li>'
                        )
                    ;

                    if (this.is_matcher == false && this.is_children_matcher == true) {
                        item.addClass('disabled');
                    }

                    itemsElement.append(item);
                    if (this.children) {
                        itemsElement.append(that.renderLevel(this.children, level + 1));
                    }
                }
            });

            return $(itemsElement).children();
        }

        , highlighter: function (item) {
            var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
            return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
                return '<strong>' + match + '</strong>'
            })
        }

        , dblclick: function () {
            this.inputChange();
        }

        , iconClick: function () {
            this.input.focus();
            this.inputClick();
        }

        , inputClick: function () {
            // this.inputChange();
            // this.query = '';
            // this.process();

            if (this.menu.find('li').length > 0) {
                this.input.removeClass('disabled');
                this.show();
            } else {
                this.valueInput.val(null);
                this.idInput.val(null);
                this.element.val(null);
                this.input.addClass('disabled');
                this.hide();
            }
        }

        , focus: function () {
            this.focused = true;
        }

        , blur: function () {
            this.focused = false;
            if (!this.mousedover && this.isShown) this.hide();
        }

        , eventSupported: function (eventName) {
            var isSupported = eventName in this.input;
            if (!isSupported) {
                this.$element.setAttribute(eventName, 'return;');
                isSupported = typeof this.input[eventName] === 'function';
            }
            return isSupported;
        }

        , move: function (e) {
            if (!this.isShown) return;

            switch (e.keyCode) {
                case 9: // tab
                case 13: // enter
                case 27: // escape
                    e.preventDefault();
                    break;

                case 38: // up arrow
                    e.preventDefault();
                    this.prev();
                    break;

                case 40: // down arrow
                    e.preventDefault();
                    this.next();
                    break;
            }

            e.stopPropagation();
        }


        , keypress: function (e) {
            if (this.suppressKeyPressRepeat) return;
            this.move(e);
        }

        , keyup: function (e) {
            switch (e.keyCode) {
                case 40: // down arrow
                case 38: // up arrow
                case 16: // shift
                case 17: // ctrl
                case 18: // alt
                    break;

                // case 9: // tab
                case 13: // enter
                    if (!this.isShown) return;
                    this.select();
                    break;

                case 27: // escape
                    if (!this.isShown) return;
                    this.hide();
                    break;

                // default:
                // this.lookup();
            }

            e.stopPropagation();
            e.preventDefault();
        }

        , keydown: function (e) {
            this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40, 38, 9, 13, 27]);
            this.move(e);
        }

        , click: function (e) {
            e.stopPropagation();
            e.preventDefault();
            this.select();
            this.input.focus();
        }

        , mouseenter: function (e) {
            if (!$(e.currentTarget).hasClass('disabled')) {
                this.mousedover = true;
                this.menu.find('.active').removeClass('active');
                $(e.currentTarget).addClass('active');
            }
        }

        , mouseleave: function () {
            this.mousedover = false;
            if (!this.focused && this.isShown) this.hide();
        }

        , next: function () {
            var active = this.menu.find('.active');

            var nextItemList = active.nextAll('li:not(.disabled)');
            if (nextItemList.length > 0) {
                var nextItem = $(nextItemList[0]);
                active.removeClass('active');
                nextItem.addClass('active');
            }

            this.offset();
        }

        , prev: function () {
            var active = this.menu.find('.active');

            var prevItemList = active.prevAll('li:not(.disabled)');
            if (prevItemList.length > 0) {
                var prevItem = $(prevItemList[0]);
                active.removeClass('active');
                prevItem.addClass('active');
            }

            this.offset();
        }

        , offset: function () {
            var active = this.menu.find('.active');
            if (active.length > 0) {
                var offsetTop = active[0].offsetTop;
                this.menu[0].scrollTop = offsetTop - 135;
            }
        }

        , select: function () {
            var text = this.menu.find('.active').find('a').attr('data-name');
            var val = this.menu.find('.active').find('a').attr('data-value');
            var id = this.menu.find('.active').find('a').attr('data-id');
            this.input.val(text);
            this.valueInput.val(val);
            this.idInput.val(id);
            this.element.val(val);
            this.hide();

            if (this.onSelected) {
                this.onSelected(this);
            }

            return this;
        }

        , isInTagSource: function (tag) {
            if (this.tagSource == null) {
                return false;
            }

            var isIn = false;
            $(this.tagSource).each(function () {
                if (this.toUpperCase() == tag.toUpperCase()) {
                    isIn = true;
                    return false;
                }
            });

            return isIn;
        }

        , isInTag1Source: function (tag1) {
            if (this.tag1Source == null) {
                return false;
            }

            var isIn = false;
            $(this.tag1Source).each(function () {
                if (this.toUpperCase() == tag1.toUpperCase()) {
                    isIn = true;
                    return false;
                }
            });

            return isIn;
        }

        , setValue: function (code) {
            var that = this;
            this.menu.find('li').each(function () {
                if ($(this).find('a').attr('data-value') == code) {
                    that.valueInput.val(code);
                    that.idInput.val($(this).find('a').attr('data-id'));
                    that.element.val(code);
                    that.input.val($(this).find('a').attr('data-name'));
                    return false;
                }
            });
            return this;
        }

        , setId: function (id) {

            this.source.length = 0;
            this.page = 0;
            this.isGetData = true;
            this.itemId = id;
            this.isAsync = false;
            this.process();

            this.listen();

            var that = this;
            this.menu.find('li').each(function () {
                if ($(this).find('a').attr('data-id') == id) {
                    that.valueInput.val($(this).find('a').attr('data-value'));
                    that.idInput.val(id);
                    that.element.val($(this).find('a').attr('data-value'));
                    that.input.val($(this).find('a').attr('data-name'));
                    return false;
                }
            });
            return this;
        }

        , getValue: function () {
            return this.valueInput.val();
        }

        , getId: function () {
            return this.idInput.val();
        }

        , getText: function () {
            return this.input.val();
        }

        , setDisabled: function (isDisabled) {
            this.isDisabled = isDisabled;
            if (isDisabled == true) {
                this.input.attr('disabled', 'disabled');
            } else {
                this.input.removeAttr('disabled');
            }
        }
    };


    $.fn.treeAutocompletePager = function (option) {
        return new TreeAutocompletePager(this, option);
    };

})(jQuery);